package jp.co.cos.ittrick.channel.service;

import java.util.Date;
import java.util.List;

import jp.co.cos.ittrick.channel.common.exception.DatastorePutException;
import jp.co.cos.ittrick.channel.common.exception.DoubleInsertException;
import jp.co.cos.ittrick.channel.meta.ArticleModelMeta;
import jp.co.cos.ittrick.channel.model.ArticleModel;

import org.slim3.datastore.Datastore;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.Transaction;


public class ArticleService {

    /**
     * キーによるクラスの取得
     * @param pkKey
     * @return ChannelModel
     */
    public ArticleModel getArticleByKey(int articleKey) {

        Key articlPkKey = Datastore.createKey(ArticleModelMeta.get(), articleKey);

        return Datastore.getOrNull(ArticleModel.class, articlPkKey);
    }

	/**
	 * すべての記事のリストの取得
	 * @return
	 */
	public List<ArticleModel> getAll() {

		ArticleModelMeta articleModelMeta = new ArticleModelMeta();

		return Datastore.query(articleModelMeta).asList();
	}

	/**
     * 記事リストを取得（publicのみ 範囲指定）
     * @return 記事リスト
     */
    public List<ArticleModel> getPublicArticleList() {

        ArticleModelMeta articleModelMeta = new ArticleModelMeta();
        List<ArticleModel> articleModelList =
            Datastore
            .query(articleModelMeta)
            .filter(articleModelMeta.publicFlg.equal(true))
            .sort(articleModelMeta.publicDate.desc)
            .asList();

        return articleModelList;
    }

	/**
	 * 記事リストを取得（publicのみ 範囲指定）
	 * @param offset
	 *             ここから
	 * @param limit
	 *             ここまで
	 * @return 記事リスト
	 */
	public List<ArticleModel> getPublicArticleList(int offset, int limit) {

		ArticleModelMeta articleModelMeta = new ArticleModelMeta();
		List<ArticleModel> articleModelList =
			Datastore
			.query(articleModelMeta)
			.filter(articleModelMeta.publicFlg.equal(true))
			.sort(articleModelMeta.publicDate.desc)
			.offset(offset)
			.limit(limit)
			.asList();

		return articleModelList;
	}


	/**
	 * 記事の登録
	 * @param serialPkKey
	 *                  連載PKキー
	 * @param articleModel
	 *                  記事Model
	 * @return 登録した記事のKey
	 * @throws DoubleInsertException
	 *                  キー重複エラー
	 * @throws DatastorePutException
	 *                  DB永久化エラー
	 */
	public Key insert(ArticleModel articleModel)
	throws DatastorePutException {

		Key key = null;
		articleModel.setLastmod(new Date());

		// Local Transaction の開始
		Transaction tx = Datastore.beginTransaction();

		try {
			key = Datastore.put(tx, articleModel);
			tx.commit();
		}
		catch (Exception e) {
			if (tx.isActive()) {
				tx.rollback();
			}
			throw new DatastorePutException();
		}

		return key;
	}


	/**
	 * 記事の更新
	 * @param articleModel
	 *                  記事Model
	 * @throws DatastorePutException
	 *                  DB永久化エラー
	 */
	public void update(ArticleModel articleModel) throws DatastorePutException {

		// Local Transaction の開始
		Transaction tx = Datastore.beginTransaction();
		articleModel.setLastmod(new Date());

		try {
			// バージョンによる変更チェック
			Datastore.get(tx, ArticleModelMeta.get(), articleModel.getKey(), articleModel.getVersion());
			// 更新
			Datastore.put(tx, articleModel);

			tx.commit();

		}catch (Exception e) {
			if (tx.isActive()) {
				tx.rollback();
			}
			throw new DatastorePutException();
		}

	}


	/**
	 * 記事Modelのみの削除
	 * @param serialpkKey
	 *                 連載PKキー
	 * @param articleNum
	 *                 記事番号
	 * @throws DatastorePutException
	 *                 DB永久化エラー
	 */
	public void delete(int articlePkKey) throws DatastorePutException {

		Key articleKey = getArticleByKey(articlePkKey).getKey();

		// Local Transaction の開始
		Transaction tx = Datastore.beginTransaction();

		try {
			Datastore.delete(tx, articleKey);

			tx.commit();

		}catch (Exception e) {
			if (tx.isActive()) {
				tx.rollback();
			}
			throw new DatastorePutException();
		}
	}

}
